package cn.com.crc.ems.rest.lucene;

import cn.com.crc.ems.rest.dto.FormStructure;
import cn.com.crc.ems.rest.dto.QueryDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.queries.TermFilter;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class LuceneUtil2 {



    private Analyzer analyzer ;

    private IndexWriterConfig config;

    private IndexWriter writer;

    private IndexReader reader;



    /**
     * 构造方法
     */
    public LuceneUtil2(@Value("${lucene.filepath}") String filePath) {
        try {
            directory = FSDirectory.open(Paths.get(filePath));
            analyzer = new IKAnalyzer(false);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("构造lucene异常:"+ e.getMessage());
        }
    }

    private Directory directory;







    /**
     * 索引更新
     */
    public void updateIndex(FormStructure formStructure) {
        try {
            config = new IndexWriterConfig(analyzer);
            writer = new IndexWriter(directory, config);

            Term term = new Term("id", formStructure.getFormId().toString());
            Document doc = new Document();
            // 表单
            Field id = new TextField("id", formStructure.getFormId() == null ? "":formStructure.getFormId().toString()  , Field.Store.YES);
            // buId
            Field buIdF = new TextField("buId", formStructure.getBuName() == null ? "":formStructure.getBuName(), Field.Store.YES);
            // content
            Field content = new TextField("content", formStructure.getContent() == null ? "":formStructure.getContent(), Field.Store.YES);
            // style
            Field style = new TextField("style", formStructure.getStyle() == null ? "":formStructure.getStyle(), Field.Store.YES);
            // mixin
            Field mixin = new TextField("mixin", formStructure.getMixin() == null ? "":formStructure.getMixin(), Field.Store.YES);

            doc.add(id);
            doc.add(buIdF);
            doc.add(content);
            doc.add(style);
            doc.add(mixin);
            //更新的时候，会把原来那个索引删掉，重新生成一个索引
            writer.updateDocument(term, doc);
            writer.commit();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("索引更新异常:"+e.getMessage());
        } finally {
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
                log.error("索引更新释放writer异常:"+e.getMessage());
            }
        }
    }


    /**
     * 索引删除
     */
    public void deleteIndex(String formId) {
        try {
            config = new IndexWriterConfig(analyzer);
            writer = new IndexWriter(directory, config);
            Term term = new Term("id", formId);
            //将id为 1和3的索引删除。
            //也可以传一个Query数组对象，将Query查找的结果删除。
            writer.deleteDocuments(term);
            //deleteDocuments
            writer.commit();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("索引删除异常:"+e.getMessage());
        } finally {
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
                log.error("索引删除释放writer异常:"+e.getMessage());
            }
        }
    }


    /**
     * 根据条件查找索引
     */
    public List<FormStructure> queryIndex(QueryDto query) {

        List<FormStructure> list = new ArrayList<>();
        try {
            //搜索器
            reader = DirectoryReader.open(directory);
            IndexSearcher searcher = new IndexSearcher(reader);

            // 构造查询的字段
            String[] queriesContent = { QueryParser.escape(query.getQuery()), QueryParser.escape(query.getQuery()), QueryParser.escape(query.getQuery()) };
            String[] fieldsContent = { "content", "style", "mixin"};

            // 查询之间的关系  SHOULD:或  MUST:与
            BooleanClause.Occur[] clausesContent = { BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD};

            // 进行查询
            Query querySContent = MultiFieldQueryParser.parse(queriesContent, fieldsContent, clausesContent, analyzer);

            // 过滤器,按照bu过滤
            Filter filter = new TermFilter(new Term("buId",query.getBuId()));

            TopDocs search = searcher.search(querySContent, filter, 1000);


            //碰撞结果
            ScoreDoc[] hits = search.scoreDocs;

            // 遍历结果
            for (int i = 0; i < hits.length; i++) {
                ScoreDoc hit = hits[i];
                    Document hitDoc = searcher.doc(hit.doc);

                    String id = hitDoc.get("id");
                    String buIdS = hitDoc.get("buId");
                    String content = hitDoc.get("content");
                    String style = hitDoc.get("style");
                    String mixin = hitDoc.get("mixin");

                    FormStructure formStructure = new FormStructure();
                    formStructure.setFormId(Integer.valueOf(id));
                    formStructure.setContent(content);
                    formStructure.setStyle(style);
                    formStructure.setMixin(mixin);
                    formStructure.setBuName(buIdS);
                    list.add(formStructure);
                }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("根据条件查找索引异常:"+e.getMessage());
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
                log.error("根据条件查找索引释放writer异常异常:"+e.getMessage());
            }

        }
        return list;
    }


    /**
     * 创建索引
     */
    public void createIndex(List<FormStructure> list) {
        try {
            config = new IndexWriterConfig(analyzer);
            writer = new IndexWriter(directory, config);
            //创建writer
            if (list != null && list.size() > 0) {
                for (FormStructure formStructure : list) {
                    Document doc = new Document();
                    // 表单
                    Field id = new TextField("id", formStructure.getFormId() == null ? "":formStructure.getFormId().toString()  , Field.Store.YES);
                    // buId
                    Field buId = new TextField("buId", formStructure.getBuName() == null ? "":formStructure.getBuName(), Field.Store.YES);
                    // content
                    Field content = new TextField("content", formStructure.getContent() == null ? "":formStructure.getContent(), Field.Store.YES);
                    // style
                    Field style = new TextField("style", formStructure.getStyle() == null ? "":formStructure.getStyle(), Field.Store.YES);
                    // mixin
                    Field mixin = new TextField("mixin", formStructure.getMixin() == null ? "":formStructure.getMixin(), Field.Store.YES);

                    doc.add(id);
                    doc.add(buId);
                    doc.add(content);
                    doc.add(style);
                    doc.add(mixin);
                    writer.addDocument(doc);
                }
                // 写入
                writer.commit();
                log.info("lucene 刷入数据成功");
            }
        } catch (IOException e) {
            log.error("lucene 刷入数据失败" , e.getMessage());
        } finally {
            try {
                writer.close();
            } catch (IOException e) {
                log.error("lucene 刷入数据释放writer失败" , e.getMessage());
            }
        }
    }
}
